<template>
  <div class="image-compressor">
    <h2>图片压缩工具</h2>
    
    <!-- 主功能区域 -->
    <div class="main-content">
      <div 
        class="upload-zone"
        @drop.prevent="handleDrop"
        @dragover.prevent
        @dragenter.prevent
        @paste="handlePaste"
      >
        <div v-if="!selectedImage" class="upload-placeholder">
          <i class="upload-icon">📁</i>
          <p>拖拽图片到这里或点击上传</p>
          <input 
            type="file" 
            @change="handleFileSelect" 
            accept="image/*"
            class="file-input"
          >
        </div>
        
        <div v-else class="preview-container">
          <div class="image-preview">
            <h3>原图</h3>
            <img 
              :src="previewUrl" 
              alt="原图预览"
              @click="showPreview(previewUrl)"
            >
            <p>大小: {{ originalSize }}</p>
          </div>
          
          <div v-if="compressedUrl" class="image-preview">
            <h3>压缩后</h3>
            <img 
              :src="compressedUrl" 
              alt="压缩后预览"
              @click="showPreview(compressedUrl)"
            >
            <p>大小: {{ compressedSize }}</p>
          </div>
        </div>
      </div>

      <div class="controls" v-if="selectedImage">
        <div class="quality-control">
          <label>压缩质量: {{ quality }}%</label>
          <input 
            type="range" 
            v-model="quality" 
            min="1" 
            max="100"
            @change="handleQualityChange"
          >
        </div>
        <div class="format-control">
          <label>输出格式:</label>
          <select v-model="outputFormat">
            <option value="auto">自动</option>
            <option value="jpeg">JPEG</option>
            <option value="png">PNG</option>
          </select>
        </div>
        <button @click="compressImage" class="compress-btn">压缩图片</button>
        <button 
          v-if="compressedUrl" 
          @click="downloadImage" 
          class="download-btn"
        >
          下载压缩图片
        </button>
      </div>
    </div>

    <!-- 功能说明区域 -->
    <div class="feature-intro">
      <details open>
        <summary>功能说明</summary>
        <div class="intro-content">
          <h3>功能简介</h3>
          <ul>
            <li>支持 JPEG 和 PNG 格式图片压缩</li>
            <li>可调节压缩质量（1-100%）</li>
            <li>可选择输出格式（自动/JPEG/PNG）</li>
            <li>实时预览压缩效果</li>
            <li>显示压缩前后文件大小对比</li>
          </ul>
          
          <h3>使用说明</h3>
          <ul>
            <li>拖拽图片到上传区域，或点击上传</li>
            <li>直接粘贴截图（Ctrl+V）</li>
            <li>调节压缩质量滑块</li>
            <li>选择期望的输出格式</li>
            <li>点击图片可放大预览（支持缩放和拖动）</li>
            <li>点击"压缩图片"开始压缩</li>
            <li>满意后点击"下载压缩图片"</li>
          </ul>
        </div>
      </details>
    </div>

    <!-- 预览弹窗 -->
    <div v-if="previewImage" class="preview-modal">
      <div 
        class="preview-content"
        :style="{
          transform: `scale(${scale}) translate(${position.x}px, ${position.y}px)`,
          cursor: isDragging ? 'grabbing' : 'grab'
        }"
        @click.stop
      >
        <img :src="previewImage" alt="预览图">
        <button class="close-btn" @click.stop="closePreview">×</button>
        <div class="zoom-controls">
          <button @click.stop="adjustScale(-0.1)">-</button>
          <span>{{ Math.round(scale * 100) }}%</span>
          <button @click.stop="adjustScale(0.1)">+</button>
          <button @click.stop="resetZoom">重置</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'ImageCompressor',
  data() {
    return {
      selectedImage: null,
      previewUrl: null,
      compressedUrl: null,
      originalSize: '0 KB',
      compressedSize: '0 KB',
      quality: 85,
      outputFormat: 'auto',
      previewImage: null,
      scale: 1,
      position: { x: 0, y: 0 },
      isDragging: false,
      dragStart: { x: 0, y: 0 },
      lastPosition: { x: 0, y: 0 }
    }
  },
  mounted() {
    document.addEventListener('paste', this.handlePaste)
  },
  beforeUnmount() {
    document.removeEventListener('paste', this.handlePaste)
  },
  methods: {
    handleDrop(e) {
      const file = e.dataTransfer.files[0]
      if (file && file.type.startsWith('image/')) {
        this.handleImage(file)
      }
    },
    handleFileSelect(e) {
      const file = e.target.files[0]
      if (file) {
        this.handleImage(file)
      }
    },
    handleImage(file) {
      this.selectedImage = file
      this.previewUrl = URL.createObjectURL(file)
      this.originalSize = this.formatFileSize(file.size)
      this.compressedUrl = null
    },
    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes'
      const k = 1024
      const sizes = ['Bytes', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    },
    async compressImage() {
      try {
        const formData = new FormData()
        formData.append('image', this.selectedImage)
        formData.append('quality', this.quality)
        formData.append('format', this.outputFormat)

        const response = await fetch('http://localhost:5000/api/compress', {
          method: 'POST',
          body: formData
        })

        const blob = await response.blob()
        
        if (blob.size > this.selectedImage.size) {
          alert('压缩后文件反而变大，建议调整压缩参数或保持原图')
        }
        
        this.compressedUrl = URL.createObjectURL(blob)
        this.compressedSize = this.formatFileSize(blob.size)
      } catch (error) {
        alert('压缩失败: ' + error.message)
      }
    },
    downloadImage() {
      const a = document.createElement('a')
      a.href = this.compressedUrl
      a.download = 'compressed_' + this.selectedImage.name
      a.click()
    },
    handleQualityChange() {
      if (this.compressedUrl) {
        this.compressImage()
      }
    },
    showPreview(url) {
      this.previewImage = url
      this.resetZoom()
      this.$nextTick(() => {
        this.$refs.modal?.focus()
      })
    },
    closePreview() {
      this.previewImage = null
      this.resetZoom()
    },
    resetZoom() {
      this.scale = 1
      this.position = { x: 0, y: 0 }
    },
    adjustScale(delta) {
      const newScale = this.scale + delta
      if (newScale >= 0.1 && newScale <= 3) {
        this.scale = newScale
      }
    },
    handleWheel(e) {
      const delta = e.deltaY > 0 ? -0.1 : 0.1
      this.adjustScale(delta)
    },
    startDrag(e) {
      if (e.button === 0) {
        this.isDragging = true
        this.dragStart = { x: e.clientX, y: e.clientY }
        this.lastPosition = { ...this.position }
      }
    },
    onDrag(e) {
      if (this.isDragging) {
        const dx = e.clientX - this.dragStart.x
        const dy = e.clientY - this.dragStart.y
        this.position = {
          x: this.lastPosition.x + dx,
          y: this.lastPosition.y + dy
        }
      }
    },
    stopDrag() {
      this.isDragging = false
    },
    handleKeydown(e) {
      switch(e.key) {
        case 'Escape':
          this.closePreview()
          break
        case '+':
        case '=':
          this.adjustScale(0.1)
          break
        case '-':
          this.adjustScale(-0.1)
          break
        case '0':
          this.resetZoom()
          break
      }
    },
    handlePaste(e) {
      const items = e.clipboardData.items
      for (let item of items) {
        if (item.type.indexOf('image') !== -1) {
          const file = item.getAsFile()
          this.handleImage(file)
          break
        }
      }
    }
  }
}
</script>

<style scoped>
.image-compressor {
  max-width: 800px;
  margin: 0 auto;
}

.upload-zone {
  border: 2px dashed #ccc;
  border-radius: 8px;
  padding: 40px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.3s;
}

.upload-zone:hover {
  border-color: #666;
}

.preview-container {
  display: flex;
  gap: 20px;
  justify-content: center;
}

.image-preview {
  flex: 1;
  max-width: 400px;
}

.image-preview img {
  max-width: 100%;
  height: auto;
  border-radius: 4px;
  cursor: pointer;
  transition: transform 0.2s;
}

.image-preview img:hover {
  transform: scale(1.02);
}

.controls {
  margin-top: 20px;
  text-align: center;
}

.quality-control {
  margin: 20px 0;
}

.quality-control input {
  width: 100%;
  margin: 10px 0;
}

button {
  padding: 10px 20px;
  margin: 0 10px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.compress-btn {
  background: #4CAF50;
  color: white;
}

.download-btn {
  background: #2196F3;
  color: white;
}

button:hover {
  opacity: 0.9;
}

.format-control {
  margin: 20px 0;
}

.format-control select {
  margin-left: 10px;
  padding: 5px;
  border-radius: 4px;
}

.preview-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
  outline: none;
}

.preview-content {
  position: relative;
  max-width: 90%;
  max-height: 90%;
  transition: transform 0.1s ease;
}

.preview-content img {
  max-width: 100%;
  max-height: 90vh;
  object-fit: contain;
  pointer-events: none;
}

.close-btn {
  position: absolute;
  top: -40px;
  right: 0;
  background: none;
  border: none;
  color: white;
  font-size: 30px;
  cursor: pointer;
}

.zoom-controls {
  position: absolute;
  bottom: -40px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.5);
  padding: 5px 10px;
  border-radius: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.zoom-controls button {
  background: none;
  border: 1px solid white;
  color: white;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin: 0;
}

.zoom-controls span {
  color: white;
  min-width: 60px;
  text-align: center;
}

.zoom-controls button:last-child {
  width: auto;
  padding: 0 10px;
  border-radius: 15px;
}

.zoom-controls button:hover {
  background: rgba(255, 255, 255, 0.2);
}

.feature-intro {
  background: #f5f5f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.feature-intro h3 {
  color: #333;
  margin-top: 15px;
  margin-bottom: 10px;
}

.feature-intro ul {
  list-style-type: none;
  padding-left: 0;
}

.feature-intro li {
  margin: 8px 0;
  padding-left: 20px;
  position: relative;
}

.feature-intro li::before {
  content: "•";
  color: #4CAF50;
  font-weight: bold;
  position: absolute;
  left: 0;
}

.main-content {
  margin-bottom: 30px;
}

.feature-intro {
  border-top: 1px solid #eee;
  padding-top: 20px;
}

.feature-intro details {
  background: #f5f5f5;
  border-radius: 8px;
  padding: 15px;
}

.feature-intro summary {
  cursor: pointer;
  font-weight: bold;
  color: #333;
  outline: none;
  padding: 5px;
}

.feature-intro summary:hover {
  color: #4CAF50;
}

.intro-content {
  padding: 15px 0;
}
</style> 